package com.ohos.connect.devicecloud.mqtt.modular.coap.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.ohos.connect.devicecloud.app.api.AppUserApi;
import com.ohos.connect.devicecloud.common.exception.CommonException;
import com.ohos.connect.devicecloud.iot.api.DeviceApi;
import com.ohos.connect.devicecloud.iot.model.dto.*;
import com.ohos.connect.devicecloud.iot.model.dto.deviceactive.DeviceActiveDTO;
import com.ohos.connect.devicecloud.iot.model.dto.deviceinfosync.DeviceInfoSyncDTO;
import com.ohos.connect.devicecloud.iot.model.vo.*;
import com.ohos.connect.devicecloud.iot.model.vo.deviceactive.DeviceActiveVO;
import com.ohos.connect.devicecloud.mqtt.api.MqttApi;
import com.ohos.connect.devicecloud.mqtt.core.model.dto.CoapToHttpDTO;
import com.ohos.connect.devicecloud.mqtt.core.model.vo.CoapToHttpVO;
import com.ohos.connect.devicecloud.mqtt.modular.coap.constant.CoapOptionConstant;
import com.ohos.connect.devicecloud.mqtt.modular.coap.constant.HttpUriConstant;
import com.ohos.connect.devicecloud.mqtt.modular.coap.service.CoapService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Service
@Slf4j
public class CoapServiceImpl implements CoapService {

    @Resource
    private DeviceApi deviceApi;

    @Autowired
    private MqttApi mqttApi;

    @Autowired
    private AppUserApi appUserApi;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Value("${iot.redis.prefix}")
    private String IOT_REDIS_PREFIX = "iot";

    @Value("${ums.coap.address}")
    private String coapAddress = "127.0.0.1:8789/coapApi/v1/cmd";

    /**
     * 获取设备上传的数据
     *
     * @param coapToHttpDTO
     * @return
     */
    public CoapToHttpVO uploadDeviceData(CoapToHttpDTO coapToHttpDTO) {
        log.info("Coap to Http With url: {}", coapToHttpDTO.getUrl());
        log.info("Coap to Http With method: {}", coapToHttpDTO.getMethod());
        log.info("Coap to Http With body: {}", coapToHttpDTO.getBody());
        log.info("Coap to Http With option: {}", JSON.toJSONString(coapToHttpDTO.getOption()));

        HashMap<String, Object> option = coapToHttpDTO.getOption();
        if (ObjectUtil.isEmpty(option) || ObjectUtil.isNull(option.get(CoapOptionConstant.SEQ_NUM_ID))) {
            throw new CommonException(CoapOptionConstant.SEQ_NUM_ID + "不能为空");
        }
        String seqNumId = option.get(CoapOptionConstant.SEQ_NUM_ID).toString();

        CoapToHttpVO coapToHttpVO = new CoapToHttpVO();

        if (HttpUriConstant.MATCH_PSK.equals(coapToHttpDTO.getUrl())) {
            JSONObject bodyObj = new JSONObject(coapToHttpDTO.getBody());
            DevicePskDTO devicePskDTO = BeanUtil.toBean(bodyObj, DevicePskDTO.class);
            DevicePskVO devicePskVO = deviceApi.exchangeDeviceSn(devicePskDTO);
            coapToHttpVO.setBody((new JSONObject(devicePskVO)).toString());
        }

        if (HttpUriConstant.ACTIVATE.equals(coapToHttpDTO.getUrl())) {
            JSONObject bodyObj = new JSONObject(coapToHttpDTO.getBody());
            DeviceActiveDTO deviceActiveDTO = BeanUtil.toBean(bodyObj, DeviceActiveDTO.class);
            DeviceActiveVO deviceActiveVO = deviceApi.activeDevice(deviceActiveDTO);
            coapToHttpVO.setBody((new JSONObject(deviceActiveVO)).toString());
        }

        if (HttpUriConstant.LOGIN.equals(coapToHttpDTO.getUrl())) {
            JSONObject bodyObj = new JSONObject(coapToHttpDTO.getBody());
            DeviceLoginDTO deviceLoginDTO = BeanUtil.toBean(bodyObj, DeviceLoginDTO.class);
            DeviceLoginVO deviceLoginVO = deviceApi.loginDevice(deviceLoginDTO);
            coapToHttpVO.setBody((new JSONObject(deviceLoginVO)).toString());
        }

        if (HttpUriConstant.DEVICE_INFO_SYNC.equals(coapToHttpDTO.getUrl())) {
            JSONArray bodyObjArray = new JSONArray(coapToHttpDTO.getBody());

            List<DeviceInfoSyncDTO> deviceInfoSyncDTOList = new ArrayList<>();
            for (Object obj : bodyObjArray) {
                DeviceInfoSyncDTO deviceInfoSyncDTO = BeanUtil.toBean(obj, DeviceInfoSyncDTO.class);
                deviceInfoSyncDTOList.add(deviceInfoSyncDTO);
            }
            DeviceInfoSyncVO deviceInfoSyncVO = deviceApi.syncDeviceInfo(deviceInfoSyncDTOList);
            coapToHttpVO.setBody((new JSONObject(deviceInfoSyncVO)).toString());
        }

        if (HttpUriConstant.DEVICE_REVOKE.equals(coapToHttpDTO.getUrl())) {
            JSONObject bodyObj = new JSONObject(coapToHttpDTO.getBody());
            DeviceRevokeDTO deviceRevokeDTO = BeanUtil.toBean(bodyObj, DeviceRevokeDTO.class);
            DeviceRevokeVO deviceRevokeVO = deviceApi.deviceRevoke(deviceRevokeDTO);
            coapToHttpVO.setBody((new JSONObject(deviceRevokeVO)).toString());
        }

        if (HttpUriConstant.DEVICE_AUTH_CODE.equals(coapToHttpDTO.getUrl())) {
            JSONObject bodyObj = new JSONObject(coapToHttpDTO.getBody());
            DeviceAuthCodeDTO deviceAuthCodeDTO = BeanUtil.toBean(bodyObj, DeviceAuthCodeDTO.class);
            DeviceAuthCodeVO deviceAuthCodeVO = deviceApi.deviceAuthCode(deviceAuthCodeDTO);
            coapToHttpVO.setBody((new JSONObject(deviceAuthCodeVO)).toString());
        }
        //桥下挂设备代理注册(暂时用不到)
        if (HttpUriConstant.DEVICE_ADD_INFO.equals(coapToHttpDTO.getUrl())) {
            JSONObject bodyObj = new JSONObject(coapToHttpDTO.getBody());
            DeviceAuthCodeDTO deviceAuthCodeDTO = BeanUtil.toBean(bodyObj, DeviceAuthCodeDTO.class);
            DeviceAuthCodeVO deviceAuthCodeVO = deviceApi.deviceAuthCode(deviceAuthCodeDTO);
            coapToHttpVO.setBody((new JSONObject(deviceAuthCodeVO)).toString());
        }
        //桥下挂设备状态同步
        if (HttpUriConstant.DEVICE_STATUS_SYNC.equals(coapToHttpDTO.getUrl())) {
            JSONArray bodyObj = new JSONArray(coapToHttpDTO.getBody());
            List<DeviceStatusSyncDTO> deviceStatusSyncDTOList = new ArrayList<>();
            for (Object obj : bodyObj) {
                DeviceStatusSyncDTO deviceStatusSyncDTO = BeanUtil.toBean(obj, DeviceStatusSyncDTO.class);
                deviceStatusSyncDTOList.add(deviceStatusSyncDTO);
            }
            List<DeviceStatusSyncVO> deviceStatusSyncVOList = deviceApi.deviceStatusSync(deviceStatusSyncDTOList);
            coapToHttpVO.setBody((new JSONArray(deviceStatusSyncVOList)).toString());
        }
        //燃气泄漏上报处理逻辑
        if (HttpUriConstant.DEVICE_LEAK_REPORT.equals(coapToHttpDTO.getUrl())) {
            JSONObject bodyObj = new JSONObject(coapToHttpDTO.getBody());
            DeviceLeakReportDTO deviceLeakReportDTO = BeanUtil.toBean(bodyObj, DeviceLeakReportDTO.class);
            DeviceLeakReportVO deviceLeakReportVO = deviceApi.deviceLeakReport(deviceLeakReportDTO);
            coapToHttpVO.setBody((new JSONObject(deviceLeakReportVO)).toString());
        }

        if (HttpUriConstant.DEVICE_HEART_BEAT.equals(coapToHttpDTO.getUrl())) {
            JSONObject bodyObj = new JSONObject(coapToHttpDTO.getBody());
            DeviceHeartBeatDTO deviceHeartBeatDTO = BeanUtil.toBean(bodyObj, DeviceHeartBeatDTO.class);
            DeviceHeartBeatVO deviceHeartBeatVO = deviceApi.deviceHeartBeat(deviceHeartBeatDTO);
            coapToHttpVO.setBody((new JSONObject(deviceHeartBeatVO)).toString());
        }
        //测试加密数据
        if (HttpUriConstant.DEVICE_SWITCH.equals(coapToHttpDTO.getUrl())) {
            JSONObject bodyObj = new JSONObject(coapToHttpDTO.getBody());
            System.out.println("测试加解密数据:" + JSONUtil.toJsonStr(coapToHttpDTO));
        }

        //获取设备信息
        if (HttpUriConstant.DEVICE_INFO.equals(coapToHttpDTO.getUrl())) {
            System.out.println("获取设备信息:" + JSONUtil.toJsonStr(coapToHttpDTO));
        }

        if (HttpUriConstant.DEVICE_DATA.equals(coapToHttpDTO.getUrl())) {
            JSONArray bodyObjArray = new JSONArray(coapToHttpDTO.getBody());

            List<DeviceDataInfoDTO> deviceDataInfoDTOList = new ArrayList<>();
            for (Object obj : bodyObjArray) {
                DeviceDataInfoDTO deviceDataInfoDTO = BeanUtil.toBean(obj, DeviceDataInfoDTO.class);
                deviceDataInfoDTOList.add(deviceDataInfoDTO);
            }
            DeviceDataVO deviceDataVO = deviceApi.deviceDataUpload(deviceDataInfoDTOList);
            coapToHttpVO.setBody((new JSONObject(deviceDataVO)).toString());
        }

        //获取设备所有快照信息
        if (HttpUriConstant.DEVICE_ALL_SERVICES.equals(coapToHttpDTO.getUrl())) {
            JSONArray bodyObjArray = new JSONArray(coapToHttpDTO.getBody());
            String devId = (String) coapToHttpDTO.getOption().get("DEV_ID");

            List<DeviceNetInfoDTO> deviceDataInfoDTOList = new ArrayList<>();
            for (Object obj : bodyObjArray) {
                DeviceNetInfoDTO deviceDataInfoDTO = BeanUtil.toBean(obj, DeviceNetInfoDTO.class);
                deviceDataInfoDTO.setDevId(devId);
                deviceDataInfoDTOList.add(deviceDataInfoDTO);
            }
            DeviceDataVO deviceDataVO = deviceApi.deviceAllShadowDataUpload(deviceDataInfoDTOList);
            coapToHttpVO.setBody((new JSONObject(deviceDataVO)).toString());
        }

        if (HttpUriConstant.DEVICE_NET_INFO.equals(coapToHttpDTO.getUrl())) {
            JSONArray bodyObjArray = new JSONArray(coapToHttpDTO.getBody());

            String devId = (String) coapToHttpDTO.getOption().get("DEV_ID");
            List<DeviceNetInfoDTO> deviceDataInfoDTOList = new ArrayList<>();
            for (Object obj : bodyObjArray) {
                DeviceNetInfoDTO deviceDataInfoDTO = BeanUtil.toBean(obj, DeviceNetInfoDTO.class);
                deviceDataInfoDTO.setDevId(devId);
                deviceDataInfoDTOList.add(deviceDataInfoDTO);
            }
            DeviceDataVO deviceDataVO = deviceApi.deviceNetInfoDataUpload(deviceDataInfoDTOList);
            coapToHttpVO.setBody((new JSONObject(deviceDataVO)).toString());
        }
        //获取控制设备返回值的逻辑
        if (HttpUriConstant.DEVICE_CONTROL.equals(coapToHttpDTO.getUrl())) {
            String devId = (String) coapToHttpDTO.getOption().get("DEV_ID");
            System.out.println("控制设备返回值设备Id:" + devId);
            JSONObject bodyObj = new JSONObject(coapToHttpDTO.getBody());
            DeviceControlDataDTO deviceControlDataDTO = BeanUtil.toBean(bodyObj, DeviceControlDataDTO.class);
            deviceControlDataDTO.setDevId(devId);
            DeviceDataVO deviceDataVO = deviceApi.deviceControlReturn(deviceControlDataDTO);
            coapToHttpVO.setBody((new JSONObject(deviceDataVO)).toString());
        }

        HashMap<String, Object> optionResult = new HashMap<>();
        optionResult.put(CoapOptionConstant.SEQ_NUM_ID, seqNumId);
        coapToHttpVO.setOption(optionResult);

        log.info("Coap to Http return : {}", JSON.toJSONString(coapToHttpVO));

        return coapToHttpVO;
    }

    @Override
    public CoapToHttpVO coapToHttpMethod(CoapToHttpDTO coapToHttpDTO) {
        CoapToHttpVO coapToHttpVO = uploadDeviceData(coapToHttpDTO);

        return coapToHttpVO;
    }

    @Override
    public CoapToHttpVO httpToCoapMethod(CoapToHttpDTO coapToHttpDTO) {
        log.info("Http to Coap With url: {}", coapToHttpDTO.getUrl());
        log.info("Http to Coap With method: {}", coapToHttpDTO.getMethod());
        log.info("Http to Coap With body: {}", coapToHttpDTO.getBody());
        log.info("Http to Coap With option: {}", JSON.toJSONString(coapToHttpDTO.getOption()));
        CoapToHttpVO coapToHttpVO = new CoapToHttpVO();
        ResponseEntity response = sendPostToCoap(coapToHttpDTO);
        if (ObjectUtil.isNotNull(response) && ObjectUtil.isNotNull(response.getBody())) {
            coapToHttpVO.setBody(response.getBody().toString());
        }
        return coapToHttpVO;
    }


    private ResponseEntity sendPostToCoap(CoapToHttpDTO coapToHttpDTO) {

        RestTemplate restTemplate = new RestTemplate();
        // 创建请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        // 将请求头和请求体包装到HttpEntity中
        HttpEntity<CoapToHttpDTO> request = new HttpEntity<>(coapToHttpDTO, headers);

        // 发送POST请求
        ResponseEntity<Object> response = restTemplate.postForEntity(coapAddress, request, Object.class);
        log.info("Http to Coap return : {}", JSON.toJSONString(response));
        // 处理响应
        if (response.getStatusCode().is2xxSuccessful()) {
            log.info("Http to Coap body return : {}", JSON.toJSONString(response.getBody()));
            System.out.println("Response: " + response.getBody());
        } else {
            System.err.println("Request failed with status code: " + response.getStatusCode());
        }
        return response;
    }

}
